<!-- 横向滚动组件 -->
<template>
    <div
        class="scroll-horizontal-wp"
        ref="container"
        @wheel.prevent="onWheel">
        <div
            class="t-list"
            ref="list"
            :style="listStyle">
            <slot></slot>
        </div>
    </div>
</template>
<script>

export default {
    props: {
        // 间隔宽度
        gap: {
            type: String,
            default: '0px'
        },
        // 空白区域宽度，如paddingLeft+paddingRight，就是：列表里面出了itemWidth和gap之外的所有宽度总和
        spaceWidth: {
            type: [String, Number],
            default: '0px'
        },
        itemClass: {
            type: String,
            default: ''
        }
    },
    data() {
        return {
            translateX: 0,
            containerWidth: 0,
            listWidth: 0,
            slotCount: 0,
            scrollPageWidth: 0, // 最大一次滚动宽度
            // 滚动锁
            isLocked: false,

            timer: null,
        };
    },
    computed: {
        listStyle() {
            let res = {
                transition: 'transform 0.3s cubic-bezier(.4,0,.2,1)',
                transform: `translateX(-${this.translateX}px)`
            }
            if(this.listWidth) {
                res.width = `${this.listWidth}px`;
            }
            return res;
        },
        arriveRight() {
            return this.translateX - this.scrollPageWidth < 0;
        },
        arriveRight() {
            return this.translateX + this.scrollPageWidth > this.listWidth;
        }
    },
    mounted() {
        this.$nextTick(() => {
            // 确保插槽渲染后计算
            this.$nextTick(this.updateSizes);
            // 监听列表尺寸变化，重新计算
            this.observeSlotChange();
        });
        window.addEventListener('resize', this.updateSizes);
    },
    beforeDestroy() {
        window.removeEventListener('resize', this.updateSizes);
        if (this.mutationObserver) {
            this.mutationObserver.disconnect();
        }
    },
    methods: {
        async updateSizes() {
            if(!this.$refs.container) {
                return;
            }
            clearTimeout(this.timer);
            this.timer = setTimeout(() => {
                // 获取容器宽度
                let containerWidth = this.$refs.container.clientWidth;
                this.containerWidth = containerWidth;

                // 计算插槽元素数量
                const slotNodes = this.$refs.list.querySelectorAll('.'+this.itemClass);
                this.slotCount = slotNodes.length;
                if(!this.slotCount) {
                    return;
                }

                // 计算列表宽度
                const itemW = slotNodes.length > 0 ? parseInt(getComputedStyle(slotNodes[0]).width) : 0;
                const gapW = parseFloat(this.gap);
                const spaceW = parseFloat(this.spaceWidth);
                this.listWidth = this.slotCount * itemW + (this.slotCount - 1) * gapW + spaceW;
                
                // 计算可视区域最大一次滚动宽度
                let width = 0;
                let isXh = true;
                while(isXh) {
                    width = width + itemW + gapW;
                    let remain = this.containerWidth - width;
                    if(remain < itemW) {
                        isXh = false;
                    }
                }
                this.scrollPageWidth = width;
            
                // 修正translateX
                if (this.translateX > Math.max(this.listWidth - this.containerWidth, 0)) {
                    this.translateX = Math.max(this.listWidth - this.containerWidth, 0);
                }
                if (this.translateX < 0) this.translateX = 0;

                // 调用事件通知父组件
                this.$nextTick(() => {
                    this.notifyScroll();
                })
            }, 16);
        },
        observeSlotChange() {
            // 监听slot变化
            this.mutationObserver = new MutationObserver(() => {
                this.$nextTick(this.updateSizes);
            });
            this.mutationObserver.observe(this.$refs.list, { childList: true, subtree: true });
        },
        onWheel(e) {
            if(this.isLocked) return; // 如果已上锁则不处理滚动
            this.isLocked = true; // 上锁防止频繁触发
            // 鼠标滚轮横向滚动
            const delta = e.deltaY || e.deltaX;
            if (delta === 0) return;

            let next = delta > 0 ? this.translateX + this.scrollPageWidth : this.translateX - this.scrollPageWidth;

            // 确保滚动不超过边界
            if(next < 0) next = 0;
            if(next > this.listWidth) next = this.translateX;

            this.translateX = next;

            // 调用事件通知父组件
            this.notifyScroll();

            setTimeout(() => {
                this.isLocked = false; // 1秒后解锁
            }, 300);
        },
        toLeft() {
            this.onWheel({deltaY: -1}); // 向左滚动
        },
        toRight() {
            this.onWheel({deltaY: 1}); // 向右滚动
        },
        // 通知父组件状态
        notifyScroll() {
            this.$emit('scroll', {
                arriveLeft: this.arriveRight, // 是否已到达最左边
                arriveRight: this.arriveRight, // 是否已到达最右边
                canScroll: this.listWidth > this.containerWidth, // 是否可以滚动
            });
        }
    }
};
</script>
<style scoped lang='scss'>
.scroll-horizontal-wp {
    padding: 0 !important;
    width: 100%;
    overflow: hidden;
    position: relative;
    user-select: none;
}
</style>